const mongodbUtil = require('./mongodbUtil');
const moment = require('moment');
const {v4: uuidv4, v4} = require('uuid');
const fs = require('fs');

/**
 * 笔记存储策略
 */
class StorageStrategy {
    async save(notes) {
        throw new Error('发生了异常');
    }

    async query() {
        throw new Error('发生了异常');
    }

    delete(noteId) {
        throw new Error('发生了异常');
    }

    update(note) {
        throw new Error('发生了异常');
    }
}

/**
 * 文件存储策略
 */
class FileStorageStrategy extends StorageStrategy {
    save(newNote) {
        console.log('将笔记保存到文件中');
        // 生成一个唯一的id
        newNote.id = uuidv4();
        let notes = readNotesFromFile();
        notes.push(newNote);
        writeNotesToFile(notes);
        console.log('保存成功：', JSON.stringify(newNote));
    }

    async query() {
        console.log('从文件中查询笔记');
        //将数组中的元素按照时间戳降序排列
        console.log(moment().format('YYYY-MM-DD HH:mm:ss') + ": 获取所有笔记");
        return await readNotesFromFile();
    }

    delete(noteId) {
        console.log(`从文件中删除笔记：${noteId}`);
        console.log(moment().format('YYYY-MM-DD HH:mm:ss') + ": 删除笔记，id：" + noteId)
        let notes = readNotesFromFile();
        notes = notes.filter((note) => note.id !== noteId);
        writeNotesToFile(notes);
    }

    update(note) {
        console.log(moment().format('YYYY-MM-DD HH:mm:ss') + ": 从文件中更新笔记，id：" + id)
        let notes = readNotesFromFile();
        // 更新id对应的笔记
        const {id} = note;
        const oldNote = notes.filter((note) => note.id === id);
        if (oldNote.length === 0) {
            throw new Error('笔记不存在');
        }
        notes = notes.filter((note) => note.id !== id);
        console.log(`id为${id}的笔记更新前：`, JSON.stringify(oldNote[0]));
        const {mainContent, clueContent, summaryContent} = note;
        const newNote = {
            mainContent,
            clueContent,
            summaryContent,
            createTime: oldNote[0].createTime,
            updateTime: moment().format('YYYY-MM-DD HH:mm:ss'),
            id: id,
        };
        console.log(`id为${id}的笔记更新后：`, JSON.stringify(newNote));
        notes.push(newNote);
        writeNotesToFile(notes);
        console.log(`id为${id}的笔记更新成功`);
    }
}

/**
 * 数据库存储策略
 */
class DatabaseStorageStrategy extends StorageStrategy {
    async save(note) {
        delete note.id; // 删除id字段
        await mongodbUtil.insert(note).then(result => {
            console.log(`将笔记插入到MongoDB中的结果为：${JSON.stringify(result)}`);
        });
    }

    async query() {
        return await mongodbUtil.getAllNotes();
    }

    async delete(noteId) {
        await mongodbUtil.deleteNote(noteId);
    }

    async update(note) {
        await mongodbUtil.updateNote(note);
    }

    async pageQueryNotes(condition) {
        return await mongodbUtil.pageQueryNotes(condition);
    }

}

const strategy = new DatabaseStorageStrategy();

const insertNote = async (reqBody) => {
    const {mainContent, clueContent, summaryContent} = reqBody;
    // 创建一个新的笔记对象, 类似于java的实体类
    const newNote = {
        mainContent: mainContent,
        clueContent: clueContent,
        summaryContent: summaryContent,
        createTime: new Date(),
        updateTime: new Date(),
    };
    await strategy.save(newNote);
};

const getAllNotes = async () => {
    return await strategy.query();
};

const pageQueryNotes = async (condition) => {
    return await strategy.pageQueryNotes(condition);
}

const deleteNote = (noteId) => {
    strategy.delete(noteId);
};

const updateNote = (reqBody) => {
    const {id, mainContent, clueContent, summaryContent} = reqBody;
    const newNote = {
        id: id,
        mainContent,
        clueContent,
        summaryContent,
        updateTime: new Date(),
    };
    strategy.update(newNote);
};

// 从文件中读取笔记数据
function readNotesFromFile() {
    // 这里要使用同步的方式读取文件，否则后面拿不到数据
    let data = fs.readFileSync('note/note.json', 'utf8');
    return JSON.parse(data);
}

// 将笔记数据写入文件
function writeNotesToFile(notes) {
    fs.writeFileSync('note/note.json', JSON.stringify(notes));
}


module.exports = {
    insertNote,
    getAllNotes,
    deleteNote,
    updateNote,
    pageQueryNotes

}
